package cn.iocoder.yudao.framework.business.basic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.pojo.bo.CreateTimeQuery;
import cn.iocoder.yudao.framework.business.basic.pojo.dto.QueryDTO;
import cn.iocoder.yudao.framework.business.basic.service.ListService;
import cn.iocoder.yudao.framework.business.basic.service.PageService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.List;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  基础服务
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/01/10
 */
@Slf4j
public abstract class BaseService<ENTITY, VO, DTO> extends AbstractService<ENTITY, VO> implements ListService<VO, DTO>, PageService<VO, DTO> {

    @Override
    public List<VO> getList(Collection<Long> ids, @Nullable Long userId) {
        if (CollUtil.isEmpty(ids)) {
            return CollUtil.newArrayList();
        }
        TableInfo tableInfo = TableInfoHelper.getTableInfo(resolveEntityClass());
        CoreQueryWrapper<ENTITY> wrapper = new CoreQueryWrapper<>();
        optimizeSelectWrapper(wrapper, null);
        wrapper.in(tableInfo.getKeyColumn(), ids);
        if (tableInfo.getFieldList().stream().anyMatch(fieldInfo -> StrUtil.equalsIgnoreCase(fieldInfo.getColumn(), "user_id"))) {
            wrapper.eqIfPresent("user_id", userId);
        }
        List<ENTITY> list = getInjectedMapper().selectList(wrapper);
        if (list == null || list.isEmpty()) {
            return CollUtil.newArrayList();
        }
        return list.stream().map(this::convertToViewObject).toList();
    }

    @Override
    public List<VO> getList(DTO param, Integer limit, @Nullable Long userId) {
        CoreQueryWrapper<ENTITY> wrapper = buildQueryWrapper(param);
        TableInfo tableInfo = TableInfoHelper.getTableInfo(resolveEntityClass());
        if (tableInfo != null && tableInfo.getFieldList().stream().anyMatch(fieldInfo -> StrUtil.equalsIgnoreCase(fieldInfo.getColumn(), "user_id"))) {
            wrapper.eqIfPresent("user_id", userId);
        }
        if (limit != null && limit > 0) {
            wrapper.limitN(limit);
        }
        return getList(wrapper);
    }

    @Override
    public PageResult<VO> getPage(Integer current, Integer size, DTO param, @Nullable Long userId) {
        CoreQueryWrapper<ENTITY> wrapper = buildQueryWrapper(param);
        TableInfo tableInfo = TableInfoHelper.getTableInfo(resolveEntityClass());
        if (tableInfo.getFieldList().stream().anyMatch(fieldInfo -> StrUtil.equalsIgnoreCase(fieldInfo.getColumn(), "user_id"))) {
            wrapper.eqIfPresent("user_id", userId);
        }
        return getPage(current, size, wrapper);
    }

    @Nonnull
    protected CoreQueryWrapper<ENTITY> buildQueryWrapper(DTO param) {
        CoreQueryWrapper<ENTITY> wrapper = new CoreQueryWrapper<>();
        if (param == null) {
            return wrapper;
        }
        TableInfo tableInfo = TableInfoHelper.getTableInfo(resolveEntityClass());
        if (tableInfo.getFieldList().stream().anyMatch(fieldInfo -> StrUtil.equalsIgnoreCase(fieldInfo.getColumn(), "create_time")) && param instanceof QueryDTO dto) {
            if (param instanceof CreateTimeQuery query) {
                wrapper.betweenIfPresent("create_time", query.buildCreateTime());
            } else {
                wrapper.betweenIfPresent("create_time", dto.getCreateTime());
            }
        }
        return wrapper;
    }

}
